package com.zte.claa.inficombo.csa.app.service.csa.impl;

import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

import org.json.JSONObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import com.zte.claa.inficombo.csa.app.comm.csif.CSIFCommService;
import com.zte.claa.inficombo.csa.app.comm.csif.CSIFConnReconnectListener;
import com.zte.claa.inficombo.csa.app.model.redis.SysLog;
import com.zte.claa.inficombo.csa.app.service.redis.CSAMessagePublisher;
import com.zte.claa.inficombo.csa.app.service.redis.PublishDataBuilder;
import com.zte.claa.inficombo.csa.app.util.JsonUtils;

public class CSIFReConnManager implements CSIFConnReconnectListener {
	private Logger logger = LoggerFactory.getLogger(CSIFReConnManager.class);
	// 认证线程数
	private int AUTH_WORKER_NUM = 5;
	// AppEUI-->CSIFCommService应用，创建时设置.
	private Map<String, CSIFCommService> appeui2CSIFMap = null;  
	
    // appEUI注册处理线程池.
    private ExecutorService appEuiAuthExecSvr;
    
    // 日志发布器.
    private CSAMessagePublisher logPublisher;
    
    // 设置log发布器》
    public void setLogPublisher(CSAMessagePublisher logPublisher){
    	this.logPublisher = logPublisher;
    }
	
	/**
	 * 构建器
	 * @param appeui2CSIFMap
	 */
	public CSIFReConnManager(Map<String, CSIFCommService> appeui2CSIFMap){
		this.appeui2CSIFMap = appeui2CSIFMap;
		this.appEuiAuthExecSvr = Executors.newFixedThreadPool(AUTH_WORKER_NUM);
	}
	
	@Override
	public void onReconnect(String appEUI) {
		logger.info("Begin to process reconnect for appeui: "+appEUI);
		this.appEuiAuthExecSvr.submit(new Runnable(){
			@Override
			public void run() {
				// appeuiAuthToCSIF(appEUI);
				// [2019-11-08]为避免CSIF的连接限制，这里采用异步忽略响应的方式认证AppEUI.
				appeuiAuthToCSIFByAsynMode(appEUI);
			}
		});
	}
	
	/**
	 * appeui认证（同步模式）
	 * 
	 * @param appEui
	 * 
	 * 	200	JOIN ACCEPT
		203	REPEAT JOIN
		401	LACK OF REQUIRED FIELD
		403	APPEUI ERROR
		405	CHALLENGE IDENTIFICATION FAILED
	 */
	private void appeuiAuthToCSIF(String appEui){
		try{
			CSIFCommService csifCSvr = this.appeui2CSIFMap.get(appEui);
			String jsonRet = csifCSvr.authToCSIF();
			logger.info("Join response: "+jsonRet);
			JSONObject json = new JSONObject(jsonRet);
			String codeVal = JsonUtils.getJsonAttrVal(json, "code", "0");
			String msg = JsonUtils.getJsonAttrVal(json, "msg", "");
			int code = Integer.parseInt(codeVal);
			if(code == 200 || code == 203){
				logger.info("Join succ: appeui="+appEui+", code="+code+", msg="+msg);
			} 
			else {
				logger.error("Join fail: appeui="+appEui+", code="+code+", msg="+msg);
				SysLog log = PublishDataBuilder.buildSysLog("AppEUI到CSIF认证失败", 
									SysLog.OP_RET_FAIL, 
									"CSA适配代理模块", 
									"CSIF认证", 
									"AppEUI Join fail: appeui="+appEui+", code="+code+", msg="+msg);
				String jsonLog = JsonUtils.toJson(log);
				logger.debug("jsonLog="+jsonLog);				
				// 发布日志（通过redis广播日志，应用服务器记录到数据库日志表中。。。
				this.logPublisher.publishMessage(jsonLog);
				if(code == 403){
					logger.warn("[*@@*]AppEUI is invalid, try to close connection to CSIF: "+appEui);
					csifCSvr.closeConnectToCSIF();
					logger.warn("[*@@*]AppEUI is invalid, close connection to CSIF ok: "+appEui);
				}
			}
		}catch(Exception e){
			logger.error("[*ERR*]appeuiAuthToCSIF failed: "+appEui, e);
		}
	}
	
	/**
	 * 异步无响应模式认证AppEUI
	 * 
	 * @param appEui
	 */
	private void appeuiAuthToCSIFByAsynMode(String appEui){
		try{
			CSIFCommService csifCSvr = this.appeui2CSIFMap.get(appEui);
			csifCSvr.authToCSIFByAsynMode();
			logger.info("authToCSIF cmd is sent, appeui : "+appEui);
		}catch(Exception e){
			logger.error("[*ERR*]appeuiAuthToCSIFByAsynMode failed: "+appEui, e);
		}
	}
	
	/**
	 * 下电
	 */
	public void shutdown(){
		this.appeui2CSIFMap = null;
		if(this.appEuiAuthExecSvr != null){
			this.appEuiAuthExecSvr.shutdown();
			this.appEuiAuthExecSvr = null;
		}
	}
	
}
